#include "positionmanager.h"
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <QMessageBox>
#include <QTextStream>
#include <QDebug>

PositionManager::PositionManager() {
    base_address = 0x000000;
    xCoord = 0x000000;
    yCoord = 0x000000;
    zCoord = 0x000000;
    xVelocityCoord = 0x000000;
    yVelocityCoord = 0x000000;
    zVelocityCoord = 0x000000;
    drakeDistSplineCoord = 0x000000;
    drakeMouvementCoord = 0x000000;
    x = 0.0;
    y = 0.0;
    z = 0.0;
    xV = 150.0;
    yV = 0.0;
    zV = 0.0;
    drakeDistSpline = 0.0;
    drakeMouvement = 1;
    DragonInited = false;
}

// 初始化
int PositionManager::init() {
    // 获取游戏窗口
    HWND game_window = (HWND) FindWindow(NULL, L"OnlyUP  ");
    if (!game_window) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "未找到游戏窗口, 请启动 OnlyUP");
        return 1;
    }

    // 获取游戏进程id
    DWORD process_id = 0;
    GetWindowThreadProcessId(game_window, &process_id);
    if (!process_id) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "获取游戏进程id失败");
        return 1;
    }

    // 获取进程
    game_process = OpenProcess(PROCESS_ALL_ACCESS, true, process_id);
    if (!game_process) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "打开游戏进程失败");
        return 1;
    }

    // 获取基地址
    const wchar_t* modName = L"OnlyUP-Win64-Shipping.exe";
    base_address = GetModuleBaseAddress(process_id, modName);
    if (!base_address) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "获取基地址失败");
        return 1;
    }

    // 初始化 內存地址
    if (initPosMemoryAddress() != 0) return 1;
    if (initVelocityMemoryAddress() != 0) return 1;
    if (initFpsMemoryAddress() != 0) return 1;
    return 0;
}

uintptr_t PositionManager::GetModuleBaseAddress(DWORD procId, const wchar_t* modName) {
    uintptr_t modBaseAddr = 0;
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
    if (hSnap != INVALID_HANDLE_VALUE) {
        MODULEENTRY32 modEntry;
        modEntry.dwSize = sizeof(modEntry);
        if (Module32First(hSnap, &modEntry)) {
            do {
                if (!_wcsicmp(modEntry.szModule, modName)) {
                    modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnap, &modEntry));
        }
    }
    else {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "初始化失败! 获取module基地址失败 !");
    }
    CloseHandle(hSnap);
    return modBaseAddr;
}

int PositionManager::initPosMemoryAddress(){
    // Déclare une variable pour stocker l'adresse actuelle + ajoutez l'offset au début de l'adresse.
    uintptr_t current_address = base_address + 0x073C5ED8;

    // 读取当前地址处游戏进程的内存以获取下一个地址
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "请开始游戏后再点击初始化 #1");
        return 1;
    }
    current_address += 0x180;

    // 读取当前地址处游戏进程的内存以获取下一个地址
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "请开始游戏后再点击初始化 #2");
        return 1;
    }
    current_address += 0xA0;

    // Répète ce processus pour chaque offset.
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "初始化失败 #3");
        return 1;
    }
    current_address += 0x98;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "初始化失败 #4");
        return 1;
    }
    current_address += 0xA8;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "初始化失败 #5");
        return 1;
    }
    current_address += 0x60;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "初始化失败 #6");
        return 1;
    }
    current_address += 0x328;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        // 对话框中显示的错误消息
        QMessageBox::critical(nullptr, "错误", "初始化失败 #7");
        return 1;
    }
    current_address += 0x270;

    zCoord = current_address;
    current_address -= 0x8;
    yCoord = current_address;
    current_address -= 0x8;
    xCoord = current_address;

    return 0;
}


int PositionManager::initVelocityMemoryAddress(){
    // Déclare une variable pour stocker l'adresse actuelle + ajoutez l'offset au début de l'adresse.
    uintptr_t current_address = base_address + 0x07356580;

    // 读取当前地址处游戏进程的内存以获取下一个地址
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化失败 #8");
        return 1;
    }

    // 读取当前地址处游戏进程的内存以获取下一个地址
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化失败 #9");
        return 1;
    }
    current_address += 0x30;

    // Répète ce processus pour chaque offset.
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化失败 #10");
        return 1;
    }
    current_address += 0xA8;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化失败 #11");
        return 1;
    }
    current_address += 0x50;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化失败 #12");
        return 1;
    }
    current_address += 0xAB8;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化失败 #13");
        return 1;
    }
    current_address += 0x20;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化失败 #14");
        return 1;
    }
    current_address += 0x320;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化失败 #15");
        return 1;
    }
    current_address += 0xC8;


    zVelocityCoord = current_address;
    current_address -= 0x8;
    yVelocityCoord = current_address;
    current_address -= 0x8;
    xVelocityCoord = current_address;

    return 0;
}

int PositionManager::initFpsMemoryAddress() {
    // Déclare une variable pour stocker l'adresse actuelle + ajoutez l'offset au début de l'adresse.
    uintptr_t current_address = base_address + 0x0788DC58;

    // Lit la mémoire du processus du jeu à l'adresse actuelle pour obtenir la prochaine adresse.
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
            // Affichage du message d'erreur dans une boîte de dialogue
            QMessageBox::critical(nullptr, "Erreur", "Erreur lors de l'initialisation des fps #25");
            return 1;
    }

    // Ajoute l'offset à l'adresse actuelle.
    current_address += 0x48;

    fpsCoord = current_address;

    // Lit la mémoire du processus du jeu à l'adresse actuelle pour obtenir la valeur des fps.
    if (!ReadProcessMemory(game_process, (void*)fpsCoord, &fps, sizeof(fps), nullptr)) {
            // Affichage du message d'erreur dans une boîte de dialogue
            QMessageBox::critical(nullptr, "Erreur", "Erreur lors de la lecture des fps #27");
            return 1;
    }

    return 0;
}

// 初始化龙内存地址
int PositionManager::initDrakeMemoryAddress(){
    // Déclare une variable pour stocker l'adresse actuelle + ajoutez l'offset au début de l'adresse.
    uintptr_t current_address = base_address + 0x07356580;
    // 读取当前地址处游戏进程的内存以获取下一个地址
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化龙错误 #17");
        return 1;
    }

    // 读取当前地址处游戏进程的内存以获取下一个地址
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化龙错误 #18");
        return 1;
    }

    // 将偏移量添加到当前地址
    current_address += 0x2B0;

    // 对每个偏移重复此过程
    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化龙错误 #19");
        return 1;
    }
    current_address += 0x170;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化龙错误 #20");
        return 1;
    }
    current_address += 0x50;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化龙错误 #21");
        return 1;
    }
    current_address += 0x28;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化龙错误 #22");
        return 1;
    }
    current_address += 0x8;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化龙错误 #23");
        return 1;
    }
    current_address += 0x70;

    if (!ReadProcessMemory(game_process, (void*)current_address, &current_address, sizeof(current_address), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化龙错误 #24");
        return 1;
    }
    current_address += 0x7C;

    drakeDistSplineCoord = current_address;
    current_address -= 0x4;
    drakeMouvementCoord = current_address;

    return 0;
}
bool PositionManager::initDrakeMemoryAddressIfNot() {
    if (!DragonInited) {
        int initResult = initDrakeMemoryAddress();
        if (initResult != 0) return false;
        drakeMouvement = 1;
        DragonInited = true;
    }
    return true;
}





float PositionManager::getFps(){
    ReadProcessMemory(game_process, (void*)fpsCoord, &fps, sizeof(fps), nullptr);
    return fps;
}

void PositionManager::setFps(float newFps){
    fps = newFps;
    WriteProcessMemory(game_process, (void*)fpsCoord, &fps, sizeof(fps), nullptr);
}




// 判断人物是否处于 攀爬 或者 静止状态
bool PositionManager::isRoleClimbOrStop()
{
    Position* p = trackRoleVelocityAndReturn();
    if (p != NULL) {
        bool result = p->x == 0 && p->y == 0 && p->z == 0;
        delete p;
        return result;
    } else {
        return false;   // 获取失败默认正常状态
    }
}


// 获取人物运动矢量
Position* PositionManager::trackRoleVelocityAndReturn()
{
    Position* position = new Position();
    if (!ReadProcessMemory(game_process, (void*)xVelocityCoord, &position->x, sizeof(position->x), nullptr)) {
        delete position;
        return NULL;
    }
    if (!ReadProcessMemory(game_process, (void*)yVelocityCoord, &position->y, sizeof(position->y), nullptr)) {
        delete position;
        return NULL;
    }
    if (!ReadProcessMemory(game_process, (void*)zVelocityCoord, &position->z, sizeof(position->z), nullptr)) {
        delete position;
        return NULL;
    }
    return position;
}


// 获取人物当前坐标
bool PositionManager::trackRolePosition(){
    if (!ReadProcessMemory(game_process, (void*)xCoord, &x, sizeof(x), nullptr)) return false;
    if (!ReadProcessMemory(game_process, (void*)yCoord, &y, sizeof(y), nullptr)) return false;
    if (!ReadProcessMemory(game_process, (void*)zCoord, &z, sizeof(z), nullptr)) return false;
    return true;
}
Position* PositionManager::trackRolePositionAndReturn()
{
    Position* position = new Position();
    if (!ReadProcessMemory(game_process, (void*)xCoord, &position->x, sizeof(position->x), nullptr)) {
        delete position;
        return NULL;
    }
    if (!ReadProcessMemory(game_process, (void*)yCoord, &position->y, sizeof(position->y), nullptr)) {
        delete position;
        return NULL;
    }
    if (!ReadProcessMemory(game_process, (void*)zCoord, &position->z, sizeof(position->z), nullptr)) {
        delete position;
        return NULL;
    }
    return position;
}

// 传送人物
void PositionManager::teleportRole(){
    WriteProcessMemory(game_process, (void*)xCoord, &x, sizeof(x), nullptr);
    WriteProcessMemory(game_process, (void*)yCoord, &y, sizeof(y), nullptr);
    WriteProcessMemory(game_process, (void*)zCoord, &z, sizeof(z), nullptr);

    WriteProcessMemory(game_process, (void*)xVelocityCoord, &xV, sizeof(x), nullptr);
    WriteProcessMemory(game_process, (void*)yVelocityCoord, &yV, sizeof(y), nullptr);
    WriteProcessMemory(game_process, (void*)zVelocityCoord, &zV, sizeof(z), nullptr);
}

bool PositionManager::loadPos(){
    return loadPositionsFromFile("pos.json");
}

double PositionManager::getX(){
    return x;
}

double PositionManager::getY(){
    return y;
}

double PositionManager::getZ(){
    return z;
}

void PositionManager::createPosition(const QString& name) {
    QJsonObject positionJson;
    positionJson["name"] = name;
    positionJson["x"] = x;
    positionJson["y"] = y;
    positionJson["z"] = z;
    positionJson["systemPosition"] = false;

    positions.insert(0, positionJson);
}

void PositionManager::savePositionsToFile(const QString& filename) {
    QJsonArray root;
    for (int i=0; i<positions.length(); ++i) {
        root.append(positions[i]);
    }
    QJsonDocument doc(root);

    QFile file(filename);
    if (!file.open(QIODevice::WriteOnly)) {
        QMessageBox::critical(nullptr, "错误", "保存坐标存档文件 " + filename + " 失败");
        return;
    }

    file.write(doc.toJson());
    file.close();
}

bool PositionManager::loadPositionsFromFile(const QString& filename)
{
    QFile file(filename);
    if (!file.open(QIODevice::ReadOnly)) {
        QMessageBox::critical(nullptr, "错误", "打开文件 " + filename + " 失败");
        return false;
    }

    QByteArray jsonData = file.readAll();
    file.close();

    QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
    if (jsonDoc.isNull()) {
        QMessageBox::critical(nullptr, "错误", "文件 " + filename + " 不是合法的json格式, 请恢复这个文件");
        return false;
    }
    QJsonArray root = jsonDoc.array();

    positions.clear();
    for (int i=0; i<root.size(); ++i) {
        positions.append(root.at(i).toObject());
    }

    return true;
}

void PositionManager::deletePosition(const int idx)
{
    const QJsonObject& position = positions[idx];
    if (position["systemPosition"].toBool()) return;

    positions.removeAt(idx);
    savePositionsToFile("pos.json");
}

void PositionManager::sortUpPosition(const int idx)
{
    if (idx <= 0) return;
    const QJsonObject position = positions[idx];    // 不能使用引用, 必须新建对象
    if (position["systemPosition"].toBool()) return;

    positions.removeAt(idx);
    positions.insert(idx-1, position);
    savePositionsToFile("pos.json");
}

void PositionManager::usePosition(const int idx){
    const QJsonObject& position = positions[idx];
    x = position.value("x").toDouble();
    y = position.value("y").toDouble();
    z = position.value("z").toDouble();
}

QList<QJsonObject> PositionManager::getPositions() const
{
    return positions;
}




// 初始化龙
int PositionManager::resetDrake(){
    if (!initDrakeMemoryAddressIfNot()) return -1;

    // 初始化坐标
    if (!WriteProcessMemory(game_process, (void*)drakeDistSplineCoord, &drakeDistSpline, sizeof(drakeDistSpline), nullptr)) {
        QMessageBox::critical(nullptr, "错误", "初始化龙失败! 需要先走到龙出生点之前的园筒, 如果还不行 重启游戏和本程序才能使用该功能 !");
        return -1;
    }

    return (int) drakeMouvement;
}

// 增加龙的移速
int PositionManager::speedUpDrake(){
    if (!initDrakeMemoryAddressIfNot()) return -1;

    ReadProcessMemory(game_process, (void*)drakeMouvementCoord, &drakeMouvement, sizeof(drakeMouvement), nullptr);
    if (drakeMouvement <= 9.00001) {
        drakeMouvement += 1;
        WriteProcessMemory(game_process, (void*)drakeMouvementCoord, &drakeMouvement, sizeof(drakeMouvement), nullptr);
    }

    return (int) drakeMouvement;
}
// 降低龙的移速
int PositionManager::speedDownDrake(){
    if (!initDrakeMemoryAddressIfNot()) return -1;

    ReadProcessMemory(game_process, (void*)drakeMouvementCoord, &drakeMouvement, sizeof(drakeMouvement), nullptr);
    if (drakeMouvement > 0.00001) {
        drakeMouvement -= 1;
        WriteProcessMemory(game_process, (void*)drakeMouvementCoord, &drakeMouvement, sizeof(drakeMouvement), nullptr);
    }

    return (int) drakeMouvement;
}
// 暂停龙
bool PositionManager::pauseDrake(){
    if (!initDrakeMemoryAddressIfNot()) return false;

    ReadProcessMemory(game_process, (void*)drakeMouvementCoord, &drakeMouvement, sizeof(drakeMouvement), nullptr);
    if (-0.001 <= drakeMouvement && drakeMouvement <= 0.001) {
        return false;
    }

    drakeMouvement = 0.0f;
    WriteProcessMemory(game_process, (void*)drakeMouvementCoord, &drakeMouvement, sizeof(drakeMouvement), nullptr);
    return true;
}
// 重置龙的移速
int PositionManager::resetSpeedDrake(){
    if (!initDrakeMemoryAddressIfNot()) return -1;

    drakeMouvement = 1.0f;
    WriteProcessMemory(game_process, (void*)drakeMouvementCoord, &drakeMouvement, sizeof(drakeMouvement), nullptr);
    return 1;
}
